<template>
  <div>
    <div v-if="mode === 'DESIGN'">
      <draggable class="l-drag-from" item-key="id" v-model="_columns" v-bind="dragProps"
                 :component-data="{tag: 'div', type: 'transition-group'}"
                @start="drag = true; selectFormItem = null" @end="drag = false">
        <template #item="{element, index}">
          <div class="l-form-item" @click.stop="selectItem(element)" :style="getSelectedClass(element)">
            <div class="l-form-header">
              <p><span v-if="element.props.required">*</span>{{ element.title }}</p>
              <div class="l-option">
                <el-icon @click="delItem(index)"><Close /></el-icon>
              </div>
              <form-design-render :config="element" />
            </div>
          </div>
        </template>
      </draggable>
      <div style="color: #c0bebe; text-align: center; width: 90%; padding: 5px">
        ☝ 拖拽控件到表格内部
      </div>
    </div>
    <div v-else-if="mode === 'MOBILE'">
      <collapse v-model="actives">
        <div class="m-tb-empty" v-if="_value.length === 0">
          点击下方 + 添加数据
        </div>
        <collapse-item :lazy-render="false" style="background: #f7f8fa" :name="i" v-for="(row, i) in _value" :key="i">
          <template #title>
            <span>第 {{ i + 1 }} 项 </span>
            <span class="m-valid-error" v-show="isError(i)">
              <el-icon><Warning /></el-icon>
            </span>
            <span class="del-row" @click.stop="delRow(i, row)" v-if="!readonly">删除</span>
          </template>
          <form-item :model="row" :rule="rules[column.id]" :ref="setItemRef"
            :prop="column.id" :label="column.title" v-for="(column, index) in _columns" :key="'column_' + index">
            <form-design-render :formData="formData" :readonly="readonly" v-model="row[column.id]" :mode="mode" :config="column"/>
          </form-item>
        </collapse-item>
      </collapse>
      <div class="m-add-row" @click="addRow" v-if="!readonly">
        <el-icon><Plus /></el-icon>
        <span> {{ placeholder }}</span>
      </div>
    </div>
    <template v-else>
      <template v-if="rowLayout">
        <el-table :cell-style="cellStyle" :header-cell-style="tbCellStyle" :border="showBorder"
          :summary-method="getSummaries" :show-summary="showSummary" :data="_value" style="width: 100%">
          <el-table-column fixed type="index" label="序号" width="55"></el-table-column>
          <el-table-column :min-width="getMinWidth(column)" v-for="(column, index) in _columns" :key="'column_' + index" :prop="column.id" :label="column.title">
            <template #header>
              <span style="color: #da4b2b" v-show="column.props.required">*</span>
              {{ column.title }}
            </template>
            <template v-slot="scope">
              <form-design-render :index="scope.$index + 1" :formData="formData"
                :class="{'valid-error': showError(column, _value[scope.$index][column.id]), readonly: readonly,}"
                v-model="_value[scope.$index][column.id]" :readonly="readonly" :mode="mode" :config="column"/>
            </template>
          </el-table-column>
          <el-table-column fixed="right" min-width="95" label="操作" v-if="!readonly">
            <template v-slot="scope">
              <el-button type="primary" link @click="copyData(scope.$index, scope.row)">复制</el-button>
              <el-button type="danger" link @click="delRow(scope.$index, scope.row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-button size="default" :icon="Plus" @click="addRow" v-if="!readonly">{{ placeholder }}</el-button>
      </template>
      <template v-else>
        <el-form :rules="rules" :model="row" :ref="setTableFormRef" class="table-column" v-for="(row, i) in _value" :key="i">
          <div class="table-column-action">
            <span>第 {{ i + 1 }} 项</span>
            <el-icon @click="delRow(i, row)" v-if="!readonly"><Close /></el-icon>
          </div>
          <el-form-item v-for="(column, index) in _columns" :key="'column_' + index" :prop="column.id" :label="column.title">
            <form-design-render :index="index + 1" :formData="formData" :readonly="readonly" v-model="row[column.id]" :mode="mode" :config="column"/>
          </el-form-item>
        </el-form>
        <el-button size="small" :icon="Plus" @click="addRow" v-if="!readonly">{{ placeholder }}</el-button>
      </template>
    </template>
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import { ValueType } from '/@/views/setting/workflow/config/ComponentsConfigExport'
import componentMinxins from '/@/views/setting/workflow/components/ComponentMinxins'
import {Collapse, CollapseItem, Dialog, showFailToast} from 'vant'
import FormItem from '/@/views/setting/workflow/common/FormItem.vue'
import FormDesignRender from '/@/views/setting/workflow/common/FormDesignRender.vue'
import { Close, Warning, Plus } from '@element-plus/icons-vue'
import { computed, onMounted, toRefs, reactive } from 'vue'
import { useWorkFlowConfig } from '/@/stores/workFlow'
import { storeToRefs } from 'pinia'
import { isNotEmpty, deepCopy } from '/@/utils/utils'
import { ElMessage, ElMessageBox } from 'element-plus'

export default {
  name: 'TableList',
  mixins: [componentMinxins],
  components: { 
    draggable, 
    FormItem, 
    Collapse, 
    CollapseItem, 
    FormDesignRender,
    Close,
    Warning,
    Plus
},
  props: {
    modelValue: {
      type: Array,
      default: () => {
        return []
      },
    },
    placeholder: {
      type: String,
      default: '添加数据',
    },
    columns: {
      type: Array,
      default: () => {
        return []
      },
    },
    showBorder: {
      type: Boolean,
      default: true,
    },
    showSummary: {
      type: Boolean,
      default: false,
    },
    maxSize: {
      type: Number,
      default: 0,
    },
    rowLayout: {
      type: Boolean,
      default: true,
    },
    formData: {
      type: Object,
      default: () => {
        return {}
      },
    },
  },
  emits: ['update:modelValue'],
  setup(props, context){
    const { modelValue, columns, mode, maxSize, rowLayout } = toRefs(props)
    const storesWorkFlowConfig = useWorkFlowConfig()
    const workFlowConfig = storeToRefs(storesWorkFlowConfig)
    let refs = []
    let tableFormRefs = []
    const state = reactive({
        select: null,
        drag: false,
        ValueType,
        actives: [],
        tbCellStyle: {
            background: '#e8e8e8',
            padding: '10px 0',
        },
        cellStyle: {
            padding: '0',
        },
        dragProps:{
            animation: 300,
            group: "form",
            disabled: false,
            sort: true,
            ghostClass: "choose",
        }
    })
    const setItemRef = el => {
        if (el) {
            refs.push(el)
        }
    }
    const setTableFormRef = el => {
        if(el) {
            tableFormRefs.push(el)
        }
    }
    console.log('TableList =>', refs)
    const rules = computed(() => {
        const rules = {}
        columns.value.forEach((col) => {
            if (col.props.required) {
            rules[col.id] = [
                {
                    type: ValueType.getValidType(col.valueType),
                    required: true,
                    message: `请完成${col.title}`,
                    trigger: 'blur',
                },
            ]
            }
        })
        return rules
    })
    const _columns = computed({
        get: () => {
            return columns.value
        },
        set: (val) => {
            context.emit('update:columns', val)
        }
    })
    const selectFormItem = computed({
        get() {
            return workFlowConfig.selectFormItem.value
        },
        set: val => {
            storesWorkFlowConfig.setSelectForm(val)
            return true
        }
    })  
    const getMinWidth = (col) => {
        switch (col.name) {
            case 'DateTime':
                return '250px'
            case 'DateTimeRange':
                return '280px'
            case 'MultipleSelect':
                return '200px'
            default:
                return '150px'
        }
    }
    const showError = (col, val) => {
        if (col.props.required) {
            switch (col.valueType) {
                case ValueType.dept:
                case ValueType.user:
                case ValueType.dateRange:
                case ValueType.array:
                    return !(Array.isArray(val) && val.length > 0)
                default:
                    return !isNotEmpty(val)
            }
        }
        return false
    }
    const isError = (i) => {
        for (let j = 0; j < _columns.value.length; j++) {
            let ref = refs.find(item => item.id == `${_columns.value[j].id}_${i}`)
            if (ref && Array.isArray(ref) && ref.length > 0 && ref[0].isError) {
                if (ref[0].isError()) {
                    return true
                }
            }
        }
        return false
    }
    const copyData = (i, row) => {
        _value.value.push(deepCopy(row))
    }
    const delRow = (i, row) => {
        if (mode.value === 'PC') {
            ElMessageBox.confirm('您确定要删除该行数据吗？', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning',
            }).then(() => {
                _value.value.splice(i, 1)
            })
        } else {
            Dialog.confirm({
                title: '提示',
                message: '您确定要删除该行数据吗？',
            }).then(() => {
                _value.value.splice(i, 1)
            })
        }
    }
    const addRow = () => {
        if (maxSize.value > 0 && _value.value.length >= maxSize.value) {
            if (mode.value === 'PC') {
                ElMessage.warning(`最多只能添加${maxSize.value}行`)
            } else {
                showFailToast(`最多加${maxSize.value}行`)
            }
        } else {
            let row = {}
            columns.value.forEach((col) => (row[col.id] = undefined))
            const v = Object.assign([], _value.value)
            v.push(row)
            _value.value = v
        }
    }
    const delItem = (id) => {
        _columns.value.splice(id, 1)
    }
    const selectItem = (cp) => {
        selectFormItem.value = cp
    }
    const getSelectedClass = (cp) => {
        return selectFormItem.value && selectFormItem.value.id === cp.id
        ? 'border-left: 4px solid #f56c6c'
        : ''
    }
    const getSummaries = (param) => {
        const { columns, data } = param
        const sums = []
        columns.forEach((column, index) => {
            if (index === 0) {
                sums[index] = '合计'
                return
            }
            const values = data.map((item) => Number(item[column.property]))
            if (!values.every((value) => isNaN(value))) {
                sums[index] = values.reduce((prev, curr) => {
                    const value = Number(curr)
                    if (!isNaN(value)) {
                        return prev + curr
                    } else {
                        return prev
                    }
                }, 0)
            } else {
                sums[index] = '...'
            }
        })
        return sums
    }
    const validate = (call) => {
        if (mode.value === 'PC') {
            if (rowLayout.value) {
                let result = true
                for (let i = 0; i < columns.value.length; i++) {
                    if (columns.value[i].props.required) {
                        for (let j = 0; j < _value.value.length; j++) {
                            result = !showError(
                                columns.value[i],
                                _value.value[j][columns.value[i].id]
                            )
                            if (!result) {
                                call(false)
                                return
                            }
                        }
                    }
                }
                call(result)
            } else {
                let success = 0
                _value.value.forEach((v, i) => {
                    let formRef = tableFormRefs.find(item => item.id == `table-form-${i}`)
                    if (formRef && Array.isArray(formRef) && formRef.length > 0) {
                        formRef[0].validate((valid) => {
                            if (valid) {
                                success++
                            }
                        })
                    }
                })
                setTimeout(() => call(success === _value.value.length),500)
            }
        } else {
            let success = true
            _value.value.forEach((row, i) => {
                _columns.value.forEach((col) => {
                    let tbColRef = refs.find(item => item.id == `${col.id}_${i}`)
                    if (tbColRef && Array.isArray(tbColRef) && tbColRef.length > 0) {
                        tbColRef[0].validate((valid) => {
                            if (!valid) {
                                success = false
                            }
                        })
                    }
                })
            })
            call(success)
        }
    }
    onMounted(() => { 
        if (!Array.isArray(modelValue.value)) {
            _value.value = []
        }
    })
    return {
        ...toRefs(state),
        Plus,
        rules,
        _columns,
        selectFormItem,
        getMinWidth,
        showError,
        isError,
        setItemRef,
        copyData,
        delRow,
        addRow,
        delItem,
        selectItem,
        getSelectedClass,
        getSummaries,
        validate,
        setTableFormRef
    }
  }
}
</script>

<style lang="scss" scoped>
.m-valid-error {
  margin-left: 10px;
  font-size: 1rem;
  color: var(--el-color-danger);
}

.readonly{
  padding: 5px 0;
}

:deep(.m-form-item .valid-error) {
  border-bottom: none;
}

.del-row {
  float:right;
  margin-right: 10px;
  font-size: 1rem;
  color: #8c8c8c;
}

:deep(.valid-error) {
  border-bottom: 2px dashed var(--el-color-danger);
}

.choose {
  border: 1px dashed var(--el-color-primary) !important;
}

:deep(.el-table__row) {
  .el-input.is-focus .el-input__wrapper {
    box-shadow: none;
  }
  .cell{
    .el-input__wrapper, .el-input__inner, .el-textarea__inner{
      border-radius: 0;
      border: none;
      padding-left: 0;
      box-shadow: none;
    }
    .el-input__prefix{
      display: none;
    }
  }
}


.table-column {
  padding: 5px;
  margin-bottom: 10px;
  border-left: 3px solid var(--el-color-primary);
  border-radius: 5px;
  background: #fafafa;

  :deep(.el-form-item) {
    margin-bottom: 20px;

    .el-form-item__label {
      height: 25px;
    }
  }

  .table-column-action {
    float: right;

    span {
      color: #afafaf;
      margin-right: 10px;
      font-size: 13px;
    }

    .icon {
      color: #afafaf;
      padding: 5px;
      font-size: large;
      cursor: pointer;

      &:hover {
        color: #666666;
      }
    }
  }
}

.l-drag-from {
  min-height: 50px;
  background-color: rgb(245, 246, 246);

  .l-form-item, li {
    cursor: grab;
    background: #ffffff;
    padding: 10px;
    border: 1px solid #ebecee;
    margin: 5px 0;
  }
}

.m-add-row {
  color: var(--el-color-primary);
  padding-top: 10px;
  text-align: center;
  cursor: pointer;
}

:deep(.van-collapse-item__content) {
  padding: 0;
  background: #f7f8fa;
}


.m-tb-empty {
  padding: 20px;
  background: #f7f8fa;
  color: #bdb7b7;
  text-align: center;
}

.l-form-header {
  font-size: small;
  color: #818181;
  text-align: left;
  position: relative;
  background-color: #fff;

  p {
    position: relative;
    margin: 0 0 10px 0;

    span {
      position: absolute;
      left: -8px;
      top: 3px;
      color: rgb(217, 0, 19);
    }
  }

  .l-option {
    position: absolute;
    top: -10px;
    right: -10px;

    .icon {
      font-size: large;
      cursor: pointer;
      color: #8c8c8c;
      padding: 5px;

      &:hover {
        color: var(--el-color-primary);
      }
    }
  }
}
</style>